package com.framework.camera;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.msgpack.type.Value;

public class NetworkControl {
/*
 * 	    このクラスは、camfw API としての全ての機能を提供します。
 */
/*
	アプリケーションは、本クラスのインスタンスを生成し、そのメソッドから各種機能を実行します。
	    arguments : string host - camfwd のホスト名、あるいはIPアドレスを指定します。
	        デフォルトは'localhost'です。
	        int port - camfwd のポート番号を指定します。デフォルトは8000です。
	    logfile - ログの出力先ファイルを指定します。無い場合、ログの出力先は標準出力となります。
	    loglevel - ログ機能のレベルを指定します。
	    レベルは5段階。本モジュールで定義している定数、CRITICAL,ERROR,WARNING,INFO,DEBUG により指定します。
	    最高がCRITICAL、最低がDEBUGです。デフォルトはWARNINGです。
	    set_loglevel(), log()メソッドにおいても同じ定数を使用します。
	        
	    
*/
	
private String lhost;
private int lport;
private InetAddress serverAddr;
//private Logger _logger;

private	Socket sock;

private FrameBuilder fb;

	    public NetworkControl(String host, int port, String logfile, Level loglevel) {
	        lhost = host;
	        lport = port;       	 

	        fb = new FrameBuilder();
	    }

	    void set_loglevel(int level) {
	    }

	    void log() {
	    }

	    void Request(int frame) {
	    	try {
                InetAddress serverAddr = InetAddress.getByName(lhost);
                sock = new Socket(serverAddr, lport);
			} catch (UnknownHostException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			} catch (IOException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
	    	
	    	
/*
	        try:
	            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
	            s.settimeout(3.0);
	            s.connect((self.host, self.port));
	            s.sendall(frame);
	            receive_string = s.recv(16384);
	            headers = self._fb.request_decode(receive_string[:35]);
	            response_length = int(headers["length"]);
	        
	            while (response_length > len(receive_string) ){
	                rdata = s.recv(16384);
	                receive_string = receive_string + rdata;
	            }

	        except socket.timeout, msg:
	            s.close()
	            s = None
	            self._logger.info(msg)
	            return False
	        except socket.error, (errno, msg) {
	            s.close()
	            s = None
	            self._logger.error(str(error) + ' : ' + msg)
	            return False

	        s.shutdown(1)
	        s.close()
	        return receive_string
*/
	    }

	    void get_apiver() {
	    }

	    private boolean ConnectSocket() {
	    	try {
				serverAddr = InetAddress.getByName(lhost);
	            sock = new Socket(serverAddr, lport);
				sock.setSoTimeout(3);
			} catch (UnknownHostException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
				return false;
			} catch (IOException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
				return false;
			}
	    	
	        return true;
	    }

	    private void CloseSocket() {
	        try {
				sock.close();
			} catch (IOException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
	    }

	    ArrayList<String> get_cameralist() {
//	        
//	        camfwd が認識しているアクティブなカメラのIDを取得します。
//
//	        arguments : なし
//	        return : 成功時はカメラのID(string)のリスト、失敗時はFalseが返る。
//	        
	    	Map<String, Value> RespFrame;
	    	ArrayList<String> dstList = new ArrayList<String>();

	    	ConnectSocket();
	    	
	    	this.fb.SendRequest(sock, fb.CAMERA_LIST, null);

	    	RespFrame = this.fb.RecieveResponse(sock);
	    	CloseSocket();

		    System.out.println(RespFrame);  // 値をダンプ

		    try {
				if(RespFrame.get("param").isMapValue() != true){
					return null;
				}
			} catch (Exception e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
		    
    		Map<Value, Value> param = RespFrame.get("param").asMapValue();
		    System.out.println(" parm  " + param);  // 値をダンプ

		    Set<Map.Entry<Value, Value>> entrySet = param.entrySet();
		    Iterator<Map.Entry<Value, Value>> it = entrySet.iterator();
		    
		    Map<Value,Value> map = new HashMap<Value, Value>();
		    //次の要素がまだ存在する場合はtrueが返される
            while(it.hasNext())
            {
                  //キーと値をセットを持つ、Map.Entry型のオブジェクトを取得する
                  Map.Entry<Value, Value> entry = it.next();
                  
                  if(entry.getKey().asRawValue().getString().equals("Response") == true){
                	  for(Iterator<Value> i = entry.getValue().asArrayValue().iterator(); i.hasNext();){
                		  String tmpStr = i.next().toString();
                		  dstList.add(tmpStr.substring(1, tmpStr.length()-1));
                	  }
                  }
                  else if(entry.getKey().asRawValue().getString().equals("Success") == true){
                	  if(entry.getValue().asBooleanValue().getBoolean() != true){
                		  return null;
                	  }
                  }
                  
                  //標準出力に表示する
//                  System.out.println(entry);
            }
	        return dstList;
	    }

	    byte[] get_snapshot(String CamId) {
//	        
//	        指定したカメラのスナップショットを取得します。
//
//	        arguments :
//	            string cid - カメラID。
//	            string filepath - スナップショット画像を保存するファイルのパスを指定。
//	        return : 成功時はTrue、失敗時はFalseが返る。
	    	byte[] data = null;
	    	Map<String, Value> RespFrame;
	    	
	    	Map<String, Object> param_in = new HashMap<String, Object>();
//	    	char[] charArray = CamId.toCharArray();
	    	param_in.put("cid", CamId);

	    	ConnectSocket();
	    	
	    	this.fb.SendRequest(sock, fb.CAMERA_SNAPSHOT, param_in);

	    	RespFrame = this.fb.RecieveResponse(sock);
	    	CloseSocket();

//		    System.out.println(RespFrame);  // 値をダンプ

		    try {
				if(RespFrame.get("param").isMapValue() != true){
					return null;
				}
			} catch (Exception e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
		    
    		Map<Value, Value> param = RespFrame.get("param").asMapValue();
//		    System.out.println(" parm  " + param);  // 値をダンプ

		    Set<Map.Entry<Value, Value>> entrySet = param.entrySet();
		    Iterator<Map.Entry<Value, Value>> it = entrySet.iterator();
		    
		    Map<Value,Value> map = new HashMap<Value, Value>();
		    //次の要素がまだ存在する場合はtrueが返される
            while(it.hasNext())
            {
                  //キーと値をセットを持つ、Map.Entry型のオブジェクトを取得する
                  Map.Entry<Value, Value> entry = it.next();
                  
                  if(entry.getKey().asRawValue().getString().equals("Response") == true){
                	  data = entry.getValue().asRawValue().getByteArray();
//                	  for(Iterator i = entry.getValue().asArrayValue().iterator(); i.hasNext();){
//                		  dstList.add(i.next().toString());
//                	  }
                  }
                  else if(entry.getKey().asRawValue().getString().equals("Success") == true){
                	  if(entry.getValue().asBooleanValue().getBoolean() != true){
                		  return null;
                	  }
                  }
                  
                  //標準出力に表示する
//                  System.out.println(entry);
            }
	    	
	    	return data;
	    	
//	        
//	        self._logger.info('get_snapshot() called, cid : ' + cid)
//
//	        params        = {}
//	        params['cid'] = cid
//
//	        s = self._socket_connect()
//	        self._fb.send_request(s, frame.CAMERA_SNAPSHOT, params)
//	        response_frame = self._fb.recv_response(s)
//	        self._socket_close(s)
//
//	        if 'param' not in response_frame:
//	            return False
//
//	        param = response_frame['param']
//	        if param['Success'] is False:
//	            self._logger.warning(param['Message'])
//	            return False
//
//	        fp = open(filepath, "w")
//	        fp.write(param['Response'])
//	        fp.close()
//	        
//	        return True
	    }

	    void restart_camera() {
	    }
	        

	    void start_movie_streaming() {
	    }

	    void stop_movie_streaming() {
	    }

	    void get_movie_imagelist() {
        }

	    void get_movie_imagedata() {
	    }

	    void start_audio_streaming() {
	    }

	    void stop_audio_streaming() {
	    }

	    void get_audio_imagelist() {
        }

	    void get_audio_imagedata() {
	    }

	    void set_framerate() {
	    }
	        

	    void set_videoparam() {
	    }
	        

	    void set_lightfrequency() {
       }
}